package org.summer.netty;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

@Slf4j
public class FirstSelector {
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        // create a server
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.bind(new InetSocketAddress(8080));
        ssc.configureBlocking(false);
        // register server socket channel
        log.info("register -> [{}]", ssc.register(selector, SelectionKey.OP_ACCEPT, null));
        for (; ; ) {
            // select events
            selector.select();
            // get events set
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();

            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                // if you don't remove this, the next loop It will always exist
                iterator.remove();
                if (selectionKey.isAcceptable()) {
                    ServerSocketChannel channel = (ServerSocketChannel) selectionKey.channel();
                    SocketChannel sc = channel.accept();
                    sc.configureBlocking(false);
                    ByteBuffer buffer = ByteBuffer.allocate(4);
                    sc.register(selector, SelectionKey.OP_READ, buffer);
                    log.info("register -> [{}]", sc);
                } else if (selectionKey.isReadable()) {
                    SocketChannel sc = null;
                    try {
                        sc = (SocketChannel) selectionKey.channel();
                        ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();
                        int read = sc.read(buffer);
                        // if read == -1 ,the client must call method close();
                        if (read == -1) {
                            log.info("from -> {} , message -> [A client is disconnected]", sc);
                            selectionKey.cancel();
                        } else {
                            PacketSplicing.split(buffer);
                            // data full dilatation buffer
                            if (buffer.position() == buffer.limit()){
                                ByteBuffer newBuffer = ByteBuffer.allocate(buffer.capacity() * 2);
                                buffer.flip();
                                newBuffer.put(buffer);
                                selectionKey.attach(newBuffer);
                            }
//                            log.info("from -> [{}] , data -> [{}] , data length -> [{}]", sc, PacketSplicing.getByteBuffData(buffer),read);
                        }
                    } catch (IOException e) {
                        log.error("from -> [{}] exception -> [{}]", sc, e.getMessage());
                        selectionKey.cancel();
                    }
                }
            }
        }

    }
}
